package com.xiyang.security.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

import javax.persistence.*;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

@Entity
@Table(name = "user",catalog = "xiyang_operater")
public class User implements Serializable {

  private static final long serialVersionUID = -3242511923360299544L;

  private Integer userId;
  private String username;
  private String password;
  private String realname;
  private Integer sex;

  // mappedBy="user"
  // 说明在两个关联的实体Bean中,role这一端是关系的拥有者,role一方的表中生成到关联类的外键
  // 且mappedBy只有在双向关联时,才会使用这个属性
 /* @OneToMany(fetch = FetchType.EAGER,mappedBy = "user") // user 是对应的实体类中 字段名，避免产生中间表
  private Set<Role> roles = new HashSet<>(0); // 对应的角色集合*/


  private Set<Role> roles;

  private Set<String> roleNames;

  public User() {}


  public User(Integer userId,String username, String password, String realname, Integer sex, Set<Role> roles, Set<String> roleNames) {
    this.userId = userId;
    this.username = username;
    this.password = password;
    this.realname = realname;
    this.sex = sex;
    this.roles = roles;
    this.roleNames = roleNames;
  }

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "user_id")
  public Integer getUserId() {
    return userId;
  }

  public void setUserId(Integer userId) {
    this.userId = userId;
  }

  @Column(name = "username",columnDefinition = "varchar(120) comment '用户账号' ")
  public String getUsername() {
    return username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  @Column(name = "password",columnDefinition = "varchar(250) comment '用户密码' ")
  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  @Column(name = "realname",columnDefinition = "varchar(120) comment '用户真名' ")
  public String getRealname() {
    return realname;
  }

  public void setRealname(String realname) {
    this.realname = realname;
  }

  @Column(name = "sex",columnDefinition = "bit(1) comment '用户性别' ")
  public Integer getSex() {
    return sex;
  }

  public void setSex(Integer sex) {
    this.sex = sex;
  }

  @Fetch(FetchMode.SUBSELECT)//默认懒加载(除非设定关联属性lazy=false),在访问第一个关联对象时加载所有的关联对象。会累计产生两条sql语句。且FetchType设定有效。
  @OneToMany(fetch = FetchType.EAGER)//一个用户可以有多个角色     会产生中间表
  @JoinTable(name = "user_role", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = {
          @JoinColumn(name = "role_id") })//joinColumns写的都是本表在中间表的外键名称， inverseJoinColumns写的是另一个表在中间表的外键名称。
  @JsonIgnore
  public Set<Role> getRoles() {
    return roles;
  }

  public void setRoles(Set<Role> roles) {
    this.roles = roles;
  }

  @Transient
  public Set<String> getRoleNames() {
    if(roleNames==null){
      roleNames=new HashSet<>();
      for (Role role : roles) {
        this.roleNames.add(role.getRolename());
      }
    }
    return roleNames;
  }

  public void setRoleNames(Set<String> roleNames) {
    this.roleNames = roleNames;
  }

  @Override
  public String toString() {
    return "User{" +
            "userId=" + userId +
            ", username='" + username + '\'' +
            ", password='" + password + '\'' +
            ", realname='" + realname + '\'' +
            ", sex=" + sex +
            ", roleNames=" + roleNames +
            '}';
  }
}
